home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Special 16
/
AMIGAplus Sonderheft 16 (1998)(ICP)(DE)[!].iso
/
pd
/
anwendungen
/
xpk_source
/
shell
/
xpk.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-08-27
|
8KB
|
370 lines
#define NAME "xPK"
#define DISTRIBUTION "(Freeware) "
#define REVISION "4"
/* Programmheader
Name: xPK
Author: SDI (before 1.2 Urban Dominik Müller)
Distribution: Freeware
Description: General XPK file-to-file packer/unpacker
Compileropts: -
Linkeropts: -l xpkmaster
1.0 : first public release
1.1 : docs written, version string added
1.2 19.10.96 : fixed an recursion error
1.3 29.11.96 : recompiled
1.4 28.11.97 : fixed little bug with chunk-hook
*/
#include "SDI_defines.h"
#define SDI_TO_ANSI
#include "SDI_ASM_STD_protos.h"
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/xpkmaster.h>
#include <exec/memory.h>
#ifdef __MAXON__
#define __asm
#define __saveds
#endif
#define lines[1000]
ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *);
STRPTR tempname(STRPTR);
STRPTR basename(STRPTR);
void doarg(STRPTR);
STRPTR dofile(STRPTR, struct FileInfoBlock *);
void end(STRPTR);
LONG isexecutable(STRPTR);
struct Hook chunkhook = {{0}, (ULONG (*) ()) chunkfunc};
struct Library *XpkBase = 0;
UBYTE errbuf[300],
*err = 0,
namebuf[200],
PrevName[100],
strbuf[200];
struct FileInfoBlock *fib = 0;
UBYTE usage[] =
"Usage: XPK [-efrsux] [-m method] [-p password] files\n"
" -e = extract files (same as -u)\n"
" -f = force packing of already packed files\n"
" -m = four letter packing method name\n"
" -p = encrypt/decrypt using password\n"
" -r = recursively (un)pack files in dir\n"
" -s = add suffix and don't delete original\n"
" -x = pack executables only\n";
UBYTE suffix = 0, force = 0, unpack = 0, recurse = 0, depth = 0, executables = 0;
STRPTR password = 0, method = 0;
void main(int argc, char **argv)
{
STRPTR c;
LONG i = 1;
if(!(XpkBase = OpenLibrary(XPKNAME, 0)) ||
!(fib = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_ANY|MEMF_CLEAR)))
end("Cannot open " XPKNAME "\n");
if(stricmp(basename(argv[0]), "XPK"))
method = basename(argv[0]);
else if(argc < 2 || !strcmp (argv[1], "?"))
end(usage);
for(; *argv[i] == '-'; i++)
for(c = argv[i] + 1; *c; c++)
{
switch (*c)
{
case 'p': password = argv[++i]; break;
case 'm': method = argv[++i]; break;
case 's': suffix = 1; break;
case 'f': force = 1; break;
case 'e':
case 'u': unpack = 1; break;
case 'r': recurse = 1; break;
case 'x': executables = 1; break;
default: end(usage);
}
if(i >= argc)
end(usage);
}
if(!method && !unpack)
end("Need a packing method, use -m\n");
if(i == argc)
end(usage);
for(; i < argc && !err; i++)
doarg(argv[i]);
end(err);
}
void iprint(STRPTR s)
{
ULONG out = Output(), i;
for(i = depth; i; --i)
Write(out, " ", 2);
Write(out, s, strlen(s));
}
void doarg(STRPTR name)
{
ULONG lock;
if(*name == 0xFF)
return;
if(!(lock = Lock(name, ACCESS_READ)))
{
sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
return;
}
if(!Examine(lock, fib))
{
UnLock(lock);
sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
return;
}
if(fib->fib_DirEntryType < 0)
{
UnLock(lock);
dofile(name, fib);
}
else if(recurse)
{
ULONG prev;
sprintf(strbuf, "Directory %s\n", name);
iprint(strbuf);
prev = CurrentDir(lock);
*PrevName = 0xFF;
while(ExNext(lock, fib) && !err)
{
if(SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
err = " *** Break";
else
{
STRPTR thisname;
ULONG i = strlen(fib->fib_FileName) + 1;
if(!(thisname = (STRPTR) AllocMem(i, MEMF_ANY)))
{
Write(Output(), "Not enough memory\n", 18);
break;
}
CopyMem(fib->fib_FileName, thisname, i);
depth++;
doarg(PrevName);
depth--;
strcpy(PrevName, thisname);
FreeMem(thisname, i);
}
}
depth++;
doarg(PrevName);
depth--;
*PrevName = 0xFF;
UnLock(CurrentDir(prev));
}
}
STRPTR dofile(STRPTR filename, struct FileInfoBlock *fib)
{
struct XpkFib xfib = {0};
UBYTE buf[100];
LONG len;
if(!force || unpack)
{
if(XpkExamineTags(&xfib, XPK_InName, (ULONG) filename, TAG_DONE))
{
sprintf(buf, "Error examining %s\n", filename);
iprint(buf);
return 0;
}
}
tempname(filename);
if(!unpack)
{
if(!force && xfib.xf_Type != XPKTYPE_UNPACKED)
{
sprintf(buf, "Skipping (already packed) %s\n", filename);
iprint(buf);
return 0;
}
if(executables && !isexecutable(filename))
return 0;
if(suffix)
sprintf(namebuf, "%s.xpk", filename);
if(XpkPackTags(
XPK_InName, (ULONG) filename,
XPK_OutName, (ULONG) namebuf,
XPK_ChunkHook, (ULONG) &chunkhook,
XPK_GetError, (ULONG) errbuf,
XPK_PackMethod, (ULONG) method,
XPK_Password, (ULONG) password,
XPK_NoClobber, TRUE,
TAG_DONE))
{
ULONG i = strlen(errbuf);
errbuf[i] = '\n'; errbuf[i+1] = '\0';
return err = errbuf;
}
}
else
{
if(xfib.xf_Type != XPKTYPE_PACKED)
{
sprintf(buf, "Skipping (already unpacked) %s\n", filename);
iprint(buf);
return 0;
}
len = strlen(filename);
suffix = 0;
if(len > 4 && !stricmp(filename + len - 5, ".xpk"))
{
strcpy(namebuf, filename);
namebuf[len - 5] = 0;
suffix = 1;
}
if(XpkUnpackTags(
XPK_InName, (ULONG) filename,
XPK_FileName, (ULONG) filename,
XPK_OutName, (ULONG) namebuf,
XPK_ChunkHook, (ULONG) &chunkhook,
XPK_Password, (ULONG) password,
XPK_GetError, (ULONG) errbuf,
XPK_NoClobber, TRUE,
TAG_DONE))
{
ULONG i = strlen(errbuf);
errbuf[i] = '\n'; errbuf[i+1] = '\0';
return err = errbuf;
}
}
if(!suffix)
{
if(!DeleteFile(filename))
return err = "Cannot delete input file\n";
if(!Rename(namebuf, filename))
return err = "Cannot rename tempfile\n";
if(*fib->fib_Comment && !SetComment(filename, fib->fib_Comment))
return err = "Cannot set original comment\n";
if(fib->fib_Protection && !SetProtection(filename, fib->fib_Protection))
return err = "Cannot set original protection bits\n";
}
}
ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *prog)
{
ULONG out = Output(), i;
UBYTE buf[180];
if(prog->xp_Type == XPKPROG_START)
Write(out, "\033[0 p", 5);
if(prog->xp_Type != XPKPROG_END)
sprintf(buf,
"%4s: %-8s (%3ld%% done, %2ld%% CF, %6ld cps) %s\033[K\r",
prog->xp_PackerName, prog->xp_Activity, prog->xp_Done,
prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
else
sprintf(buf,
"%4s: %-8s (%3ldK, %2ld%% CF, %6ld cps) %s\033[K\n",
prog->xp_PackerName, prog->xp_Activity, prog->xp_ULen / 1024,
prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
iprint(buf);
if(prog->xp_Type == XPKPROG_END)
Write(out, "\033[1 p", 5);
if((i = SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C))
Write(out, "\n", 1);
return i;
}
STRPTR tempname(STRPTR name)
{
strcpy(namebuf, name);
for(name = namebuf + strlen (namebuf); name > namebuf; name--)
if(name[-1] == '/' || name[-1] == ':')
break;
sprintf(name, "tmp%lx", &name);
return namebuf;
}
LONG isexecutable(STRPTR name)
{
ULONG fh;
BPTR buf[5];
UBYTE msg[100];
LONG len;
if(!(fh = Open(name, MODE_OLDFILE)))
{
sprintf(msg, "Cannot open %s\n", name);
iprint(msg);
return 0;
}
len = Read(fh, (void *) buf, 20);
Close(fh);
if(len < 20 || buf[0] != 0x3f3 || buf[1] != 0)
{
sprintf(msg, "%s not executable\n", name);
iprint(msg);
return 0;
}
if(buf[3] != 0 || buf[4] + 1 != buf[2])
{
sprintf(msg, "%s overlayed\n", name);
iprint(msg);
return 0;
}
return 1;
}
STRPTR basename(STRPTR name)
{
STRPTR ret = name;
for(; *name; ++name)
{
if(*name == ':' || *name == '/')
ret = name + 1;
}
return ret;
}
void end(STRPTR text)
{
if(text) Write(Output(), text, strlen(text));
if(XpkBase) CloseLibrary(XpkBase);
if(fib) FreeMem(fib, sizeof(struct FileInfoBlock));
exit(text ? 10 : 0);
}